<template>
	<template v-if="list.length > 0 && current===courseNo">
		<div class="chart-wrapper" v-for="(item, index) in list" :key="index">
			<div :ref="el => setChartRef(el, index)" class="chart-container"></div>
		</div>
	</template>
	<el-empty v-else description="暂无课程章节知识图谱" />
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import { getKnowledgePointsChartBySectionNo } from '/@/api/course';

const props = defineProps({
	chapterNo: {
		type: String,
		default: ''
	},
	courseNo: {
		type: String,
		default: ''
	},
	current: {
		type: String,
		default: ''
	},
});

// 初始化ref数组
const chartRefs = ref<(HTMLElement | null)[]>([]);
const charts = ref<(echarts.ECharts | null)[]>([]);
const resizeHandlers = ref<((() => void) | null)[]>([]);
let list = ref<any[]>([]);

// 安全地设置ref引用
const setChartRef = (el: HTMLElement | null, index: number) => {
	if (index >= chartRefs.value.length) {
		for (let i = chartRefs.value.length; i <= index; i++) {
			chartRefs.value[i] = null;
		}
	}
	chartRefs.value[index] = el;
};

// 生成唯一ID的辅助函数
const generateUniqueId = (baseId: string | number, chartIndex: number) => {
	// 结合图表索引和基础ID，确保跨图表的ID唯一性
	return `chart-${chartIndex}-node-${baseId}`;
};

onMounted(async () => {
	try {
		const res = await getKnowledgePointsChartBySectionNo(props.chapterNo);
		list.value = res.data?[res.data]:[];


		charts.value = new Array(list.value.length).fill(null);
		resizeHandlers.value = new Array(list.value.length).fill(null);

		await nextTick();

		list.value.forEach((item, chartIndex) => {
			if (chartIndex < 0 || chartIndex >= chartRefs.value.length) {
				console.error(`无效的图表索引: ${chartIndex}`);
				return;
			}

			const container = chartRefs.value[chartIndex];
			if (!container) {
				console.error(`图表容器不存在，索引: ${chartIndex}`);
				return;
			}

			// 销毁旧实例
			if (charts.value[chartIndex]) {
				charts.value[chartIndex]!.dispose();
			}

			const myChart = echarts.init(container);
			charts.value[chartIndex] = myChart;

			const containerWidth = container.offsetWidth;
			const containerHeight = container.offsetHeight;
			const totalHeight = containerHeight - 100;
			const nodeCount = item.data?.length || 0;

			// 存储当前图表中已使用的ID，确保唯一性
			const usedIds = new Set<string>();

			// 处理数据 - 确保ID唯一
			if (item.data && Array.isArray(item.data)) {
				item.data.forEach((child: any, dataIndex: number) => {
					if (typeof child !== 'object' || child === null) {
						console.warn(`无效的数据项，图表索引: ${chartIndex}, 数据索引: ${dataIndex}`);
						return;
					}

					// 生成基础ID
					let baseId = child.knowledgePointsNo?.toString() || dataIndex.toString();

					// 确保ID在当前图表中唯一
					let uniqueId = generateUniqueId(baseId, chartIndex);
					let counter = 1;
					while (usedIds.has(uniqueId)) {
						uniqueId = generateUniqueId(`${baseId}-${counter}`, chartIndex);
						counter++;
					}

					usedIds.add(uniqueId);
					child.id = uniqueId;
				});
			}

			// 处理链接数据 - 使用上面生成的唯一ID
			const links = (item.link || []).map((linkItem: any) => {
				// 找到对应的源节点和目标节点
				const sourceNode = item.data?.find((n: any) =>
					n.knowledgePointsNo?.toString() === linkItem.from?.toString()
				);
				const targetNode = item.data?.find((n: any) =>
					n.knowledgePointsNo?.toString() === linkItem.to?.toString()
				);

				return {
					...linkItem,
					// 使用节点实际的唯一ID
					source: sourceNode?.id || generateUniqueId(linkItem.from || 'unknown-source', chartIndex),
					target: targetNode?.id || generateUniqueId(linkItem.to || 'unknown-target', chartIndex)
				};
			});

			// 设置图表配置
			const option = {
				title: {
					left: 'center',
					top: '10px',
					textStyle: { fontSize: 14 },
				},
				tooltip: {},
				animationDurationUpdate: 1500,
				animationEasingUpdate: 'quinticInOut',
				series: [
					{
						type: 'graph',
						zoom: 0.7,
						layout: 'force',
						force: {
							repulsion: 1000, // 节点之间的斥力，值越大斥力越大，可根据实际情况调整
							gravity: 0.1, // 节点向中心的引力，值越大引力越大
							edgeLength: 200 // 边的长度，影响节点间距
						},
						symbolSize: 60,
						roam: true,
						label: {
							show: true,
							fontSize: 12,
							formatter: (params: any) => {
								// 获取节点数据中的level属性，如果没有则显示0
								const level = params.data.level || 0;
								return [
									`{name|${params.data.name}}`,
									`{b|ladder: ${params.data.ladder}}`
								].join('\n');
							},
							rich: {
								a: {
									fontSize: 12,
									textShadowBlur: 2,
									textShadowColor: 'rgba(255,255,255,0.5)'
								},
								b: {
									fontSize: 12,
									align: 'center',textShadowBlur: 2,
									textShadowColor: 'rgba(255,255,255,0.5)'
								}
							}
						},
						edgeSymbol: ['circle', 'arrow'],
						edgeSymbolSize: [4, 10],
						edgeLabel: {
							show: false
						},
						data: item.data,
						links: links,
						lineStyle: {
							opacity: 0.9,
							width: 2,
							curveness: 0.1
						}
					}
				],
			};

			myChart.setOption(option);

			// 移除旧的resize事件
			if (resizeHandlers.value[chartIndex]) {
				window.removeEventListener('resize', resizeHandlers.value[chartIndex]!);
			}

			// 响应式适配
			const resizeHandler = () => {
				if (!myChart || !container) return;

				const newWidth = container.offsetWidth;
				const newHeight = container.offsetHeight;
				const newTotalHeight = newHeight - 100;

				if (item.data && Array.isArray(item.data)) {
					item.data.forEach((dataItem: any, dataIndex: number) => {
						if (typeof dataItem !== 'object' || dataItem === null) return;
						dataItem.x = newWidth / 2;
						dataItem.y = 50 + (nodeCount - 1 - dataIndex) * (newTotalHeight / (nodeCount - 1 || 1));
					});
				}

				myChart.setOption({ series: [{ data: item.data || [] }] });
				myChart.resize({ width: newWidth, height: newHeight });
			};

			resizeHandlers.value[chartIndex] = resizeHandler;
			window.addEventListener('resize', resizeHandler);
		});
	} catch (error) {
		console.error('初始化图表失败:', error);
	}
});

</script>

<style scoped lang="scss">


.chart-wrapper {
	margin-bottom: 30px;
	border: 1px solid #eee;
	border-radius: 8px;
	padding: 10px;
	.chart-container {
		width: 100%;
		min-width: 800px;
		height: 300px;
	}
}

</style>

